home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / DELPHI / EZDSL200.ZIP / EZDSLBTR.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-03-13  |  41.2 KB  |  1,357 lines

  1. {===EZDSLBTR==========================================================
  2.  
  3. Part of the Delphi Structures Library--the binary tree, the binary
  4. search tree and the red-black binary search tree.
  5.  
  6. EZDSLBTR is Copyright (c) 1993, 1996 by  Julian M. Bucknall
  7.  
  8. VERSION HISTORY
  9. 13Mar96 JMB 2.00 release for Delphi 2.0
  10. 18Jun95 JMB 1.00 conversion of EZStrucs to Delphi
  11. ======================================================================}
  12. { Copyright (c) 1993, 1996, Julian M. Bucknall. All Rights Reserved   }
  13.  
  14. unit EZDSLBtr;
  15.  
  16. {$I EZDSLDEF.INC}
  17. {---Place any compiler options you require here-----------------------}
  18.  
  19.  
  20. {---------------------------------------------------------------------}
  21. {$I EZDSLOPT.INC}
  22.  
  23. interface
  24.  
  25. uses
  26.   SysUtils,
  27.   WinTypes,
  28.   WinProcs,
  29.   Classes,
  30.   EZDSLCts,
  31.   EZDSLSup,
  32.   EZDSLBse,
  33.   {$IFNDEF UseTreeRecursion}
  34.   EZDSLStk,
  35.   {$ENDIF}
  36.   EZDSLQue;
  37.  
  38. type
  39.   TBinTree = class(TAbstractContainer)
  40.     {-Binary tree object}
  41.     private
  42.       Rt        : PNode;
  43.       FTravType : TTraversalType;
  44.  
  45.     public
  46.       constructor Create(DataOwner : boolean); override;
  47.       constructor Clone(Source : TAbstractContainer;
  48.                         DataOwner : boolean; NewCompare : TCompareFunc); override;
  49.  
  50.       function  Delete(Cursor : TTreeCursor) : TTreeCursor; virtual;
  51.       procedure Empty; override;
  52.       function  Erase(Cursor : TTreeCursor) : TTreeCursor;
  53.       function  Examine  (Cursor : TTreeCursor) : pointer;
  54.       procedure Insert   (var Cursor : TTreeCursor; aData : pointer); virtual;
  55.       function  IsLeaf   (Cursor : TTreeCursor) : boolean;
  56.       function  IsRoot   (Cursor : TTreeCursor) : boolean;
  57.       function  Iterate(Action : TIterator; Backwards : boolean;
  58.                         ExtraData : pointer) : TTreeCursor;
  59.       procedure Join(Cursor : TTreeCursor; Tree : TBinTree); virtual;
  60.       function  Left(Cursor : TTreeCursor) : TTreeCursor;
  61.       function  Parent(Cursor : TTreeCursor) : TTreeCursor;
  62.       function  Replace  (Cursor : TTreeCursor; aData : pointer) : pointer; virtual;
  63.       function  Right(Cursor : TTreeCursor) : TTreeCursor;
  64.       function  Root : TTreeCursor;
  65.       function  Search   (var Cursor : TTreeCursor; aData : pointer) : boolean; virtual;
  66.  
  67.       property TraversalType : TTraversalType
  68.          read FTravType
  69.          write FTravType;
  70.   end;
  71.  
  72.   TBinSearchTree = class(TBinTree)
  73.     {-Binary search tree object}
  74.     protected
  75.       procedure bsSwapData(OldCursor, NewCursor : TTreeCursor); virtual;
  76.  
  77.     public
  78.       constructor Clone(Source : TAbstractContainer;
  79.                         DataOwner : boolean; NewCompare : TCompareFunc); override;
  80.  
  81.       function  Delete (Cursor : TTreeCursor) : TTreeCursor; override;
  82.       procedure Insert (var Cursor : TTreeCursor; aData : pointer); override;
  83.       procedure Join(Cursor : TTreeCursor; Tree : TBinTree); override;
  84.       function  Replace(Cursor : TTreeCursor; aData : pointer) : pointer; override;
  85.       function  Search (var Cursor : TTreeCursor; aData : pointer) : boolean; override;
  86.   end;
  87.  
  88.   TrbSearchTree = class(TBinSearchTree)
  89.     {-Balanced binary search tree object (Red-black tree)}
  90.     private
  91.       DeletedNodeWasBlack : boolean;
  92.  
  93.     protected
  94.       procedure bsSwapData(OldCursor, NewCursor : TTreeCursor); override;
  95.       function  rbPromote(Cursor : TTreeCursor) : TTreeCursor;
  96.  
  97.     public
  98.       function  Delete (Cursor : TTreeCursor) : TTreeCursor; override;
  99.       procedure Insert (var Cursor : TTreeCursor; aData : pointer); override;
  100.   end;
  101.  
  102. implementation
  103.  
  104. {Notes: the TTreeCursor is a pointer and a boolean wrapped in one. In
  105.         Delphi, pointers allocated on the heap have a granularity of
  106.         4 bytes, ie their offset always has the lower 2 bits clear.
  107.         We use bit 0 of the pointer as a left child, right child
  108.         indicator (left = 0, right = 1). Thus the TTreeCursor is a
  109.         pointer to the parent's node and an indicator to the relevant
  110.         child.
  111.         The parent link field of a node (the PKC) is a pointer and two
  112.         booleans wrapped in one. The pointer is the parent's node as
  113.         for TTreeCursors, bit 0 is the child (so a node always knows
  114.         which child it is) and we use bit 1 of the pointer as a color
  115.         bit for red-black trees (black = 0, red = 1). This by the way
  116.         violates pure OOP design where ancestor aren't supposed to
  117.         'know' about their descendants, but as I wrote the binary
  118.         tree implementations in one go...
  119.         The following 6 routines all help maintain these 'packed'
  120.         variables.                                                    }
  121.  
  122. {-Given a cursor, returns the address of node's parent node}
  123. function Dad(X : TTreeCursor) : PNode;
  124.   {$IFDEF Win32}
  125.   begin
  126.     Result := PNode(X and $FFFFFFFC);
  127.   end;
  128.   {$ELSE}
  129.   inline($58/            {pop ax      get offset}
  130.          $25/$FC/$FF/    {and ax, XX  clear color and child bits}
  131.          $5A);           {pop dx      get seg/sel}
  132.   {$ENDIF}
  133. {--------}
  134. {-Given a cursor, returns the child relationship the node has with its parent}
  135. function Kid(X : TTreeCursor) : TChild;
  136.   {$IFDEF Win32}
  137.   begin
  138.     Result := TChild(X and $1);
  139.   end;
  140.   {$ELSE}
  141.   inline($58/            {pop ax      get offset}
  142.          $25/$01/$00/    {and ax, 1   isolate child bit}
  143.          $5A);           {pop dx      toss seg/sel}
  144.   {$ENDIF}
  145. {--------}
  146. {-Given a cursor, returns the address of the node being pointed to}
  147. function GetNode(Cursor : TTreeCursor) : PNode;
  148.   {$IFDEF Win32}
  149.   register;
  150.   asm
  151.     mov edx, eax
  152.     and edx, 1
  153.     shl edx, 2
  154.     and eax, $FFFFFFFC
  155.     mov eax, [eax+edx+4]
  156.   end;
  157.   {$ELSE}
  158.   near; assembler;
  159.   asm
  160.     mov ax, Cursor.Word[2]
  161.     mov es, ax
  162.     mov di, Cursor.Word[0]
  163.     mov ax, di
  164.     and ax, $FFFC
  165.     xchg ax, di
  166.     and ax, 1
  167.     shl ax, 1
  168.     shl ax, 1
  169.     add di, ax
  170.     mov ax, es:[di+4]
  171.     mov dx, es:[di+6]
  172.   end;
  173.   {$ENDIF}
  174. {--------}
  175. {-Converts a parent node and child relationship into a cursor}
  176. function Csr(P : PNode; C : TChild) : TTreeCursor;
  177.   {$IFDEF Win32}
  178.   begin
  179.     Result := TTreeCursor(longint(P) or Ord(C))
  180.   end;
  181.   {$ELSE}
  182.   inline($58/            {pop ax      get child}
  183.          $25/$01/$00/    {and ax, 1   isolate child bit}
  184.          $5B/            {pop bx      get offset}
  185.          $09/$D8/        {or ax, bx   xfer child bit}
  186.          $5A);           {pop dx      get seg/sel}
  187.   {$ENDIF}
  188. {--------}
  189. {-Sets the cursor's color bit to zero}
  190. function Bleach(Cursor : TTreeCursor) : TTreeCursor;
  191.   {$IFDEF Win32}
  192.   begin
  193.     Result := (Cursor and $FFFFFFFD);
  194.   end;
  195.   {$ELSE}
  196.   inline ($58/           {pop ax      get offset}
  197.           $25/$FD/$FF/   {and ax, XX  set off color bit}
  198.           $5A);          {pop dx      get seg/sel}
  199.   {$ENDIF}
  200. {--------}
  201. {-Sets the cursor's color bit to the same as a PKC link}
  202. function Dye(Cursor, PKC : TTreeCursor) : TTreeCursor;
  203.   {$IFDEF Win32}
  204.   begin
  205.     Result := (Cursor and $FFFFFFFD) or (PKC and $2);
  206.   end;
  207.   {$ELSE}
  208.   inline ($58/             {pop ax      get color word}
  209.           $25/$02/$00/     {and ax, 2   isolate color bit}
  210.           $5B/             {pop bx      toss next}
  211.           $5B/             {pop bx      get offset}
  212.           $81/$E3/$FD/$FF/ {and bx, XX  kill color}
  213.           $09/$D8/         {or ax, bx   xfer color bit}
  214.           $5A);            {pop dx      get seg/sel}
  215.   {$ENDIF}
  216.  
  217. {=TBinTree============================================================
  218. A simple binary tree.
  219.  
  220. A binary tree is a data structure where each node has up to two
  221. children, and one parent. This implementation makes a distinction
  222. between external nodes (that have no children at all) and internal
  223. nodes (that always have two children). External nodes are called
  224. leaves. The object uses external cursors to navigate the tree (these
  225. are NOT the nodes themselves). You position a given cursor in the tree
  226. by moving it with the object's methods, and can use a cursor to insert
  227. and delete data objects in the tree (although there are restrictions
  228. on where this can happen).
  229.  
  230. The object has two iterators, and four methods to traverse the tree
  231. with them. The four traversal methods are pre-order, in-order,
  232. post-order and level-order. Note that JDS can be compiled in two modes
  233. distinguished by the compiler define: UseTreeRecursion. If this is
  234. active, recursive routines are used wherever required to implement
  235. traversals; if not, then a TStack will be used to unravel the
  236. recursion.
  237. ======================================================================}
  238. constructor TBinTree.Create(DataOwner : boolean);
  239.   begin
  240.     NodeSize := 16;
  241.     inherited Create(DataOwner);
  242.  
  243.     FTravType := ttInOrder;
  244.  
  245.     Rt := acNewNode(nil);
  246.     FCount := 0;
  247.   end;
  248. {--------}
  249. constructor TBinTree.Clone(Source : TAbstractContainer;
  250.                            DataOwner : boolean;
  251.                            NewCompare : TCompareFunc);
  252.   var
  253.     OldTree : TBinTree absolute Source;
  254.     NewData : pointer;
  255.  
  256.   {$IFDEF UseTreeRecursion}
  257.   procedure CloneTree(OldWalker, NewWalker : TTreeCursor);
  258.     var
  259.       Temp, NewTemp : TTreeCursor;
  260.     begin
  261.       NewData := nil;
  262.       try
  263.         Temp := OldTree.Left(OldWalker);
  264.         if not OldTree.IsLeaf(Temp) then
  265.           begin
  266.             if DataOwner then
  267.                  NewData := DupData(OldTree.Examine(Temp))
  268.             else NewData := OldTree.Examine(Temp);
  269.             NewTemp := Left(NewWalker);
  270.             Insert(NewTemp, NewData);
  271.             NewData := nil;
  272.             CloneTree(Temp, NewTemp);
  273.           end;
  274.         Temp := OldTree.Right(OldWalker);
  275.         if not OldTree.IsLeaf(Temp) then
  276.           begin
  277.             if DataOwner then
  278.                  NewData := DupData(OldTree.Examine(Temp))
  279.             else NewData := OldTree.Examine(Temp);
  280.             NewTemp := Right(NewWalker);
  281.             Insert(NewTemp, NewData);
  282.             NewData := nil;
  283.             CloneTree(Temp, NewTemp);
  284.           end;
  285.       finally
  286.         if DataOwner and Assigned(NewData) then
  287.           DisposeData(NewData);
  288.       end;
  289.     end;
  290.   {$ELSE}
  291.   procedure CloneTree;
  292.     var
  293.       StackOld, StackNew : TStack;
  294.       OldWalker, NewWalker : TTreeCursor;
  295.       Temp, NewTemp : TTreeCursor;
  296.       Color : longint;
  297.     begin
  298.       StackOld := nil;
  299.       StackNew := nil;
  300.       NewData := nil;
  301.       try
  302.         StackOld := TStack.Create(false);
  303.         StackNew := TStack.Create(false);
  304.         if DataOwner then
  305.              NewData := DupData(OldTree.Examine(OldTree.Root))
  306.         else NewData := OldTree.Examine(OldTree.Root);
  307.         NewTemp := Root;
  308.         Insert(NewTemp, NewData);
  309.         NewData := nil;
  310.         StackOld.Push(pointer(OldTree.Root));
  311.         StackNew.Push(pointer(Root));
  312.         repeat
  313.           OldWalker := TTreeCursor(StackOld.Pop);
  314.           NewWalker := TTreeCursor(StackNew.Pop);
  315.           Temp := OldTree.Left(OldWalker);
  316.           if not OldTree.IsLeaf(Temp) then
  317.             begin
  318.               if DataOwner then
  319.                    NewData := DupData(OldTree.Examine(Temp))
  320.               else NewData := OldTree.Examine(Temp);
  321.               NewTemp := Left(NewWalker);
  322.               Insert(NewTemp, NewData);
  323.               NewData := nil;
  324.               StackOld.Push(pointer(Temp));
  325.               StackNew.Push(pointer(NewTemp));
  326.             end;
  327.           Temp := OldTree.Right(OldWalker);
  328.           if not OldTree.IsLeaf(Temp) then
  329.             begin
  330.               if DataOwner then
  331.                    NewData := DupData(OldTree.Examine(Temp))
  332.               else NewData := OldTree.Examine(Temp);
  333.               NewTemp := Right(NewWalker);
  334.               Insert(NewTemp, NewData);
  335.               NewData := nil;
  336.               StackOld.Push(pointer(Temp));
  337.               StackNew.Push(pointer(NewTemp));
  338.             end;
  339.         until StackOld.IsEmpty;
  340.       finally
  341.         StackOld.Free;
  342.         StackNew.Free;
  343.         if DataOwner and Assigned(NewData) then
  344.           DisposeData(NewData);
  345.       end;
  346.     end;
  347.   {$ENDIF}
  348.   var
  349.     NewTemp : TTreeCursor;
  350.   begin
  351.     Create(DataOwner);
  352.     Compare := NewCompare;
  353.     DupData := OldTree.DupData;
  354.     DisposeData := OldTree.DisposeData;
  355.  
  356.     if not (Source is TBinTree) then
  357.       RaiseError(escBadSource);
  358.  
  359.     if OldTree.IsEmpty then Exit;
  360.  
  361.     try
  362.       NewData := nil;
  363.       {$IFDEF UseTreeRecursion}
  364.       if DataOwner then
  365.            NewData := DupData(OldTree.Examine(OldTree.Root))
  366.       else NewData := OldTree.Examine(OldTree.Root);
  367.       NewTemp := Root;
  368.       Insert(NewTemp, NewData);
  369.       NewData := nil;
  370.       CloneTree(OldTree.Root, Root);
  371.       {$ELSE}
  372.       CloneTree;
  373.       {$ENDIF}
  374.     except
  375.       if DataOwner and Assigned(NewData) then
  376.         DisposeData(NewData);
  377.       raise;
  378.     end;{try..except}
  379.   end;
  380. {--------}
  381. function TBinTree.Delete(Cursor : TTreeCursor) : TTreeCursor;
  382.   var
  383.     NewKid,
  384.     LeftKid,
  385.     RightKid : TTreeCursor;
  386.     NodeToGo,
  387.     Node : PNode;
  388.   begin
  389.     if IsLeaf(Cursor) then
  390.       RaiseError(escDelInvalidHere);
  391.     RightKid := Right(Cursor);
  392.     LeftKid := Left(Cursor);
  393.     if not IsLeaf(RightKid) then
  394.       if not IsLeaf(LeftKid) then
  395.         RaiseError(escDelInvalidHere)
  396.       else
  397.         NewKid := RightKid
  398.     else
  399.       NewKid := LeftKid;
  400.     Delete := Cursor;
  401.     Node := GetNode(NewKid);
  402.     NodeToGo := GetNode(Cursor);
  403.     Dad(Cursor)^.TLink[Kid(Cursor)] := Node;
  404.     if not IsLeaf(NewKid) then
  405.       with Node^ do
  406.         PKC := Dye(Cursor, PKC);
  407.     acDisposeNode(NodeToGo);
  408.   end;
  409. {--------}
  410. procedure TBinTree.Empty;
  411. {$IFDEF UseTreeRecursion}
  412.   {------}
  413.   procedure RecursePostOrder(Cursor : TTreeCursor);
  414.     begin
  415.       if not IsLeaf(Cursor) then
  416.         begin
  417.           RecursePostOrder(Left(Cursor));
  418.           RecursePostOrder(Right(Cursor));
  419.           if IsDataOwner then
  420.             DisposeData(Examine(Cursor));
  421.           acDisposeNode(GetNode(Cursor));
  422.         end;
  423.     end;
  424.   {------}
  425.   begin
  426.     if not IsEmpty then
  427.       begin
  428.         RecursePostOrder(Root);
  429.         Rt^.TLink[CRight] := nil;
  430.       end;
  431.     if InDone then
  432.       if Assigned(Rt) then
  433.         acDisposeNode(Rt);
  434.   end;
  435. {$ELSE}
  436.   const
  437.     Sentinel = 0;
  438.   var
  439.     Walker: TTreeCursor;
  440.     Stack : TStack;
  441.   begin
  442.     if not IsEmpty then
  443.       begin
  444.         Stack := TStack.Create(false);
  445.         try
  446.           Stack.Push(pointer(Root));
  447.           repeat
  448.             Walker := TTreeCursor(Stack.Examine);
  449.             if (Walker = Sentinel) then
  450.               begin
  451.                 Walker := TTreeCursor(Stack.Pop);
  452.                 Walker := TTreeCursor(Stack.Pop);
  453.                 if IsDataOwner then
  454.                   DisposeData(Examine(Walker));
  455.                 acDisposeNode(GetNode(Walker));
  456.               end
  457.             else
  458.               begin
  459.                 Stack.Push(pointer(Sentinel));
  460.                 if not IsLeaf(Right(Walker)) then
  461.                   Stack.Push(pointer(Right(Walker)));
  462.                 if not IsLeaf(Left(Walker)) then
  463.                   Stack.Push(pointer(Left(Walker)));
  464.               end;
  465.           until (Stack.IsEmpty);
  466.         finally
  467.           Stack.Free;
  468.         end;{try..finally}
  469.         Rt^.TLink[CRight] := nil;
  470.       end;
  471.     if InDone then
  472.       if Assigned(Rt) then
  473.         acDisposeNode(Rt);
  474.   end;
  475. {$ENDIF}
  476. {--------}
  477. function TBinTree.Erase(Cursor : TTreeCursor) : TTreeCursor;
  478.   begin
  479.     if IsDataOwner then
  480.       DisposeData(Examine(Cursor));
  481.     Erase := Delete(Cursor);
  482.   end;
  483. {--------}
  484. function  TBinTree.Examine(Cursor : TTreeCursor) : pointer;
  485.   begin
  486.     {$IFDEF DEBUG}
  487.     Assert(not IsEmpty, ascEmptyExamine);
  488.     Assert(not IsLeaf(Cursor), ascExamineLeaf);
  489.     {$ENDIF}
  490.     Examine := GetNode(Cursor)^.Data;
  491.   end;
  492. {--------}
  493. procedure TBinTree.Insert(var Cursor : TTreeCursor; aData : pointer);
  494.   var
  495.     Node : PNode;
  496.   begin
  497.     if not IsLeaf(Cursor) then
  498.       RaiseError(escInsInvalidHere)
  499.     else
  500.       begin
  501.         Node := acNewNode(aData);
  502.         Node^.PKC := Cursor;
  503.         Dad(Cursor)^.TLink[Kid(Cursor)] := Node;
  504.       end;
  505.   end;
  506. {--------}
  507. function  TBinTree.IsLeaf(Cursor : TTreeCursor) : boolean;
  508.   begin
  509.     IsLeaf := GetNode(Cursor) = nil;
  510.   end;
  511. {--------}
  512. function  TBinTree.IsRoot(Cursor : TTreeCursor) : boolean;
  513.   begin
  514.     IsRoot := Dad(Cursor) = Rt;
  515.   end;
  516. {--------}
  517. function  TBinTree.Iterate(Action : TIterator; Backwards : boolean;
  518.                            ExtraData : pointer) : TTreeCursor;
  519.   {------}
  520.   function TraverseLevelOrder : TTreeCursor;
  521.     var
  522.       Finished : boolean;
  523.       Walker: TTreeCursor;
  524.       Queue : TQueue;
  525.     begin
  526.       TraverseLevelOrder := 0;
  527.       Finished := false;
  528.       Queue := TQueue.Create(false);
  529.       try
  530.         Queue.Append(pointer(Root));
  531.         repeat
  532.           Walker := TTreeCursor(Queue.Pop);
  533.           if not Action(Self, Examine(Walker), ExtraData) then  {!!.01}
  534.             begin
  535.               TraverseLevelOrder := Walker;
  536.               Finished := true;
  537.             end
  538.           else if Backwards then
  539.             begin
  540.               if not IsLeaf(Right(Walker)) then
  541.                 Queue.Append(pointer(Right(Walker)));
  542.               if not IsLeaf(Left(Walker)) then
  543.                 Queue.Append(pointer(Left(Walker)));
  544.             end
  545.           else
  546.             begin
  547.               if not IsLeaf(Left(Walker)) then
  548.                 Queue.Append(pointer(Left(Walker)));
  549.               if not IsLeaf(Right(Walker)) then
  550.                 Queue.Append(pointer(Right(Walker)));
  551.             end;
  552.         until Finished or Queue.IsEmpty;
  553.       finally
  554.         Queue.Free;
  555.       end;{try..finally}
  556.     end;
  557.   {------}
  558. {$IFDEF UseTreeRecursion}
  559.   function TraversePreOrder(Walker : TTreeCursor) : TTreeCursor;
  560.     begin
  561.       Result := 0;
  562.       if not IsLeaf(Walker) then
  563.         if not Action(Self, Examine(Walker), ExtraData) then    {!!.01}
  564.           Result := Walker
  565.         else
  566.           begin
  567.             Result := TraversePreOrder(Left(Walker));
  568.             if (Result = 0) then
  569.               Result := TraversePreOrder(Right(Walker));
  570.           end;
  571.     end;
  572.   {------}
  573.   function TraverseInOrder(Walker : TTreeCursor) : TTreeCursor;
  574.     begin
  575.       Result := 0;
  576.       if not IsLeaf(Walker) then
  577.         begin
  578.           Result := TraverseInOrder(Left(Walker));
  579.           if (Result = 0) then
  580.             if not Action(Self, Examine(Walker), ExtraData) then {!!.01}
  581.               Result := Walker
  582.             else
  583.               Result := TraverseInOrder(Right(Walker));
  584.         end;
  585.     end;
  586.   {------}
  587.   function TraversePostOrder(Walker : TTreeCursor) : TTreeCursor;
  588.     begin
  589.       Result := 0;
  590.       if not IsLeaf(Walker) then
  591.         begin
  592.           Result := TraversePostOrder(Left(Walker));
  593.           if (Result = 0) then
  594.             begin
  595.               Result := TraversePostOrder(Right(Walker));
  596.               if (Result = 0) then
  597.                 if not Action(Self, Examine(Walker), ExtraData) then {!!.01}
  598.                   Result := Walker;
  599.             end;
  600.         end;
  601.     end;
  602.   {------}
  603.   function TraversePreOrderRev(Walker : TTreeCursor) : TTreeCursor;
  604.     begin
  605.       Result := 0;
  606.       if not IsLeaf(Walker) then
  607.         if not Action(Self, Examine(Walker), ExtraData) then    {!!.01}
  608.           Result := Walker
  609.         else
  610.           begin
  611.             Result := TraversePreOrderRev(Right(Walker));
  612.             if (Result = 0) then
  613.               Result := TraversePreOrderRev(Left(Walker));
  614.           end;
  615.     end;
  616.   {------}
  617.   function TraverseInOrderRev(Walker : TTreeCursor) : TTreeCursor;
  618.     begin
  619.       Result := 0;
  620.       if not IsLeaf(Walker) then
  621.         begin
  622.           Result := TraverseInOrderRev(Right(Walker));
  623.           if (Result = 0) then
  624.             if not Action(Self, Examine(Walker), ExtraData) then {!!.01}
  625.               Result := Walker
  626.             else
  627.               Result := TraverseInOrderRev(Left(Walker));
  628.         end;
  629.     end;
  630.   {------}
  631.   function TraversePostOrderRev(Walker : TTreeCursor) : TTreeCursor;
  632.     begin
  633.       Result := 0;
  634.       if not IsLeaf(Walker) then
  635.         begin
  636.           Result := TraversePostOrderRev(Right(Walker));
  637.           if (Result = 0) then
  638.             begin
  639.               Result := TraversePostOrderRev(Left(Walker));
  640.               if (Result = 0) then
  641.                 if not Action(Self, Examine(Walker), ExtraData) then {!!.01}
  642.                   Result := Walker;
  643.             end;
  644.         end;
  645.     end;
  646.   {------}
  647.   begin
  648.     if Backwards then
  649.       case FTravType of
  650.         ttPreOrder   : Result := TraversePreOrderRev(Root);
  651.         ttInOrder    : Result := TraverseInOrderRev(Root);
  652.         ttPostOrder  : Result := TraversePostOrderRev(Root);
  653.         ttLevelOrder : Result := TraverseLevelOrder;
  654.       end{case}
  655.     else
  656.       case FTravType of
  657.         ttPreOrder   : Result := TraversePreOrder(Root);
  658.         ttInOrder    : Result := TraverseInOrder(Root);
  659.         ttPostOrder  : Result := TraversePostOrder(Root);
  660.         ttLevelOrder : Result := TraverseLevelOrder;
  661.       end;{case}
  662.   end;
  663. {$ELSE}
  664.   const
  665.     Sentinel = 0;
  666.   function TraversePreOrder : TTreeCursor;
  667.     var
  668.       Walker: TTreeCursor;
  669.       Stack : TStack;
  670.       Finished : boolean;
  671.     begin
  672.       Result := 0;
  673.       Finished := false;
  674.       Stack := TStack.Create(false);
  675.       try
  676.         Stack.Push(pointer(Root));
  677.         repeat
  678.           Walker := TTreeCursor(Stack.Pop);
  679.           if not Action(Self, Examine(Walker), ExtraData) then  {!!.01}
  680.             begin
  681.               Result := Walker;
  682.               Finished := true;
  683.             end
  684.           else if Backwards then
  685.             begin
  686.               if not IsLeaf(Left(Walker)) then
  687.                 Stack.Push(pointer(Left(Walker)));
  688.               if not IsLeaf(Right(Walker)) then
  689.                 Stack.Push(pointer(Right(Walker)));
  690.             end
  691.           else
  692.             begin
  693.               if not IsLeaf(Right(Walker)) then
  694.                 Stack.Push(pointer(Right(Walker)));
  695.               if not IsLeaf(Left(Walker)) then
  696.                 Stack.Push(pointer(Left(Walker)));
  697.             end;
  698.         until Finished or Stack.IsEmpty;
  699.       finally
  700.         Stack.Free;
  701.       end;{try..finally}
  702.     end;
  703.   {------}
  704.   function TraverseInOrder : TTreeCursor;
  705.     var
  706.       Walker: TTreeCursor;
  707.       Stack : TStack;
  708.       Finished : boolean;
  709.     begin
  710.       Result := 0;
  711.       Finished := false;
  712.       Stack := TStack.Create(false);
  713.       try
  714.         Stack.Push(pointer(Root));
  715.         repeat
  716.           Walker := TTreeCursor(Stack.Pop);
  717.           if (Walker = Sentinel) then
  718.             begin
  719.               Walker := TTreeCursor(Stack.Pop);
  720.               if not Action(Self, Examine(Walker), ExtraData) then {!!.01}
  721.                 begin
  722.                   Result := Walker;
  723.                   Finished := true;
  724.                 end;
  725.             end
  726.           else if Backwards then
  727.             begin
  728.               if not IsLeaf(Left(Walker)) then
  729.                 Stack.Push(pointer(Left(Walker)));
  730.               Stack.Push(pointer(Walker));
  731.               Stack.Push(pointer(Sentinel));
  732.               if not IsLeaf(Right(Walker)) then
  733.                 Stack.Push(pointer(Right(Walker)));
  734.             end
  735.           else
  736.             begin
  737.               if not IsLeaf(Right(Walker)) then
  738.                 Stack.Push(pointer(Right(Walker)));
  739.               Stack.Push(pointer(Walker));
  740.               Stack.Push(pointer(Sentinel));
  741.               if not IsLeaf(Left(Walker)) then
  742.                 Stack.Push(pointer(Left(Walker)));
  743.             end;
  744.         until Finished or Stack.IsEmpty;
  745.       finally
  746.         Stack.Free;
  747.       end;{try..finally}
  748.     end;
  749.   {------}
  750.   function TraversePostOrder : TTreeCursor;
  751.     var
  752.       Walker: TTreeCursor;
  753.       Stack : TStack;
  754.       Finished : boolean;
  755.     begin
  756.       Result := 0;
  757.       Finished := false;
  758.       Stack := TStack.Create(false);
  759.       try
  760.         Stack.Push(pointer(Root));
  761.         repeat
  762.           Walker := TTreeCursor(Stack.Examine);
  763.           if (Walker = Sentinel) then
  764.             begin
  765.               Walker := TTreeCursor(Stack.Pop);
  766.               Walker := TTreeCursor(Stack.Pop);
  767.               if not Action(Self, Examine(Walker), ExtraData) then {!!.01}
  768.                 begin
  769.                   Result := Walker;
  770.                   Finished := true;
  771.                 end;
  772.             end
  773.           else if Backwards then
  774.             begin
  775.               Stack.Push(pointer(Sentinel));
  776.               if not IsLeaf(Left(Walker)) then
  777.                 Stack.Push(pointer(Left(Walker)));
  778.               if not IsLeaf(Right(Walker)) then
  779.                 Stack.Push(pointer(Right(Walker)));
  780.             end
  781.           else
  782.             begin
  783.               Stack.Push(pointer(Sentinel));
  784.               if not IsLeaf(Right(Walker)) then
  785.                 Stack.Push(pointer(Right(Walker)));
  786.               if not IsLeaf(Left(Walker)) then
  787.                 Stack.Push(pointer(Left(Walker)));
  788.             end;
  789.         until Finished or Stack.IsEmpty;
  790.       finally
  791.         Stack.Free;
  792.       end;{try..finally}
  793.     end;
  794.   {------}
  795.   begin
  796.     if IsEmpty then
  797.       Result := 0
  798.     else
  799.       case FTravType of
  800.         ttPreOrder   : Result := TraversePreOrder;
  801.         ttInOrder    : Result := TraverseInOrder;
  802.         ttPostOrder  : Result := TraversePostOrder;
  803.         ttLevelOrder : Result := TraverseLevelOrder;
  804.       end;{case}
  805.   end;
  806. {$ENDIF}
  807. {--------}
  808. procedure TBinTree.Join(Cursor : TTreeCursor; Tree : TBinTree);
  809.   var
  810.     RootNode : PNode;
  811.   begin
  812.     if not IsLeaf(Cursor) then
  813.       RaiseError(escInsInvalidHere)
  814.     else
  815.       if Assigned(Tree) then
  816.         begin
  817.           if not Tree.IsEmpty then
  818.             begin
  819.               RootNode := GetNode(Tree.Root);
  820.               RootNode^.PKC := Cursor;
  821.               Dad(Cursor)^.TLink[Kid(Cursor)] := RootNode;
  822.               inc(FCount, Tree.Count);
  823.               {patch up Tree}
  824.               with Tree do
  825.                 begin
  826.                   Rt^.TLink[CRight] := nil;
  827.                   FCount := 0;
  828.                 end;
  829.             end;
  830.           Tree.Free;
  831.       end;
  832.   end;
  833. {--------}
  834. function  TBinTree.Left(Cursor : TTreeCursor) : TTreeCursor;
  835.   begin
  836.     if IsLeaf(Cursor) then
  837.       RaiseError(escCannotMoveHere)
  838.     else
  839.       Left := Csr(GetNode(Cursor), CLeft);
  840.   end;
  841. {--------}
  842. function  TBinTree.Parent(Cursor : TTreeCursor) : TTreeCursor;
  843.   begin
  844.     if IsRoot(Cursor) then
  845.       RaiseError(escCannotMoveHere)
  846.     else
  847.       Parent := Bleach(Dad(Cursor)^.PKC);
  848.   end;
  849. {--------}
  850. function  TBinTree.Replace(Cursor : TTreeCursor; aData : pointer) : pointer;
  851.   begin
  852.     {$IFDEF DEBUG}
  853.     Assert(not IsLeaf(Cursor), ascExamineLeaf);
  854.     {$ENDIF}
  855.     with GetNode(Cursor)^ do
  856.        begin
  857.          Replace := Data;
  858.          Data := aData;
  859.        end;
  860.   end;
  861. {--------}
  862. function  TBinTree.Right(Cursor : TTreeCursor) : TTreeCursor;
  863.   begin
  864.     if IsLeaf(Cursor) then
  865.       RaiseError(escCannotMoveHere)
  866.     else
  867.       Right := Csr(GetNode(Cursor), CRight);
  868.   end;
  869. {--------}
  870. function  TBinTree.Root : TTreeCursor;
  871.   begin
  872.     Root := Csr(Rt, CRight);
  873.   end;
  874. {--------}
  875. function  TBinTree.Search(var Cursor : TTreeCursor; aData : pointer) : boolean;
  876. {$IFDEF UseTreeRecursion}
  877.   {------}
  878.   function RecursePreOrder(Walker : TTreeCursor) : boolean;
  879.     begin
  880.       if IsLeaf(Walker) then
  881.         RecursePreOrder := false
  882.       else if (Compare(Examine(Walker), aData) = 0) then
  883.         begin
  884.           RecursePreOrder := true;
  885.           Cursor := Walker;
  886.         end
  887.       else if RecursePreOrder(Left(Walker)) then
  888.         RecursePreOrder := true
  889.       else
  890.         RecursePreOrder := RecursePreOrder(Right(Walker));
  891.     end;
  892.   {------}
  893.   begin
  894.     Search := RecursePreOrder(Root);
  895.   end;
  896. {$ELSE}
  897.   var
  898.     Walker: TTreeCursor;
  899.     Stack : TStack;
  900.     FoundIt : boolean;
  901.   begin
  902.     FoundIt := false;
  903.     Stack := TStack.Create(false);
  904.     try
  905.       Stack.Push(pointer(Root));
  906.       repeat
  907.         Walker := TTreeCursor(Stack.Pop);
  908.         if (Compare(Examine(Walker), aData) = 0) then
  909.           begin
  910.             FoundIt := true;
  911.             Cursor := Walker;
  912.           end
  913.         else
  914.           begin
  915.             if not IsLeaf(Right(Walker)) then
  916.               Stack.Push(pointer(Right(Walker)));
  917.             if not IsLeaf(Left(Walker)) then
  918.               Stack.Push(pointer(Left(Walker)));
  919.           end;
  920.       until FoundIt or Stack.IsEmpty;
  921.     finally
  922.       Stack.Free;
  923.     end;{try..finally}
  924.     Search := FoundIt;
  925.   end;
  926. {$ENDIF}
  927. {---------------------------------------------------------------------}
  928.  
  929. {-An iterator for cloning a binary search tree}
  930. function BSTreeCloneData(C : TAbstractContainer;
  931.                          aData : pointer;
  932.                          ExtraData : pointer) : boolean; far;
  933.   var
  934.     NewTree : TBinTree absolute ExtraData;
  935.     DummyCursor : TTreeCursor;
  936.     NewData : pointer;
  937.   begin
  938.     Result := true;
  939.     NewData := nil;
  940.     try
  941.       with NewTree do
  942.         begin
  943.           if IsDataOwner then
  944.                NewData := DupData(aData)
  945.           else NewData := aData;
  946.           Insert(DummyCursor, NewData);
  947.         end;
  948.     except
  949.       if NewTree.IsDataOwner then
  950.         NewTree.DisposeData(NewData);
  951.       raise;
  952.     end;{try..except}
  953.   end;
  954.  
  955. {-An iterator for joining a binary search tree}
  956. function BSTreeJoinData(C : TAbstractContainer;
  957.                         aData : pointer;
  958.                         ExtraData : pointer) : boolean; far;
  959.   var
  960.     OurTree : TBinSearchTree absolute ExtraData;
  961.     DummyCursor : TTreeCursor;
  962.   begin
  963.     Result := true;
  964.     OurTree.Insert(DummyCursor, aData);
  965.   end;
  966.  
  967. {=TBinSearchTree======================================================
  968. A binary search tree
  969.  
  970. A sorted binary tree where for any given data object, all data objects
  971. in its left subtree are less than it, and all data objects in the
  972. right subtree are greater than it. This ordering relies on the Compare
  973. method to be overridden.
  974. ======================================================================}
  975. constructor TBinSearchTree.Clone(Source : TAbstractContainer;
  976.                                  DataOwner : boolean;
  977.                                  NewCompare : TCompareFunc);
  978.   var
  979.     OldTree : TBinSearchTree absolute Source;
  980.     SaveTravType : TTraversalType;
  981.   begin
  982.     Create(DataOwner);
  983.     Compare := NewCompare;
  984.     DupData := OldTree.DupData;
  985.     DisposeData := OldTree.DisposeData;
  986.  
  987.     if not (Source is TBinTree) then
  988.       RaiseError(escBadSource);
  989.  
  990.     if OldTree.IsEmpty then Exit;
  991.  
  992.     SaveTravType := OldTree.TraversalType;
  993.     OldTree.TraversalType := ttPostOrder;
  994.     try
  995.       OldTree.Iterate(BSTreeCloneData, false, Self);
  996.     finally
  997.       OldTree.TraversalType := SaveTravType;
  998.     end;{try..finally}
  999.   end;
  1000. {--------}
  1001. function  TBinSearchTree.Delete (Cursor : TTreeCursor) : TTreeCursor;
  1002.   var
  1003.     Walker,
  1004.     LeftChild : TTreeCursor;
  1005.   begin
  1006.     if IsLeaf(Cursor) then
  1007.       RaiseError(escDelInvalidHere);
  1008.     if IsLeaf(Left(Cursor)) or IsLeaf(Right(Cursor)) then
  1009.       Delete := inherited Delete(Cursor)
  1010.     else {both children exist}
  1011.       begin
  1012.         Walker := Right(Cursor);
  1013.         LeftChild := Left(Walker);
  1014.         while not IsLeaf(LeftChild) do
  1015.           begin
  1016.             Walker := LeftChild;
  1017.             LeftChild := Left(Walker);
  1018.           end;
  1019.         bsSwapData(Cursor, Walker);
  1020.         Delete := inherited Delete(Walker);
  1021.       end;
  1022.   end;
  1023. {--------}
  1024. procedure TBinSearchTree.Insert(var Cursor : TTreeCursor; aData : pointer);
  1025.   begin
  1026.     if Search(Cursor, aData) then
  1027.       RaiseError(escInsertDup)
  1028.     else
  1029.       inherited Insert(Cursor, aData);
  1030.   end;
  1031. {--------}
  1032. procedure TBinSearchTree.Join(Cursor : TTreeCursor; Tree : TBinTree);
  1033.   begin
  1034.     if Assigned(Tree) then
  1035.       with Tree do
  1036.         begin
  1037.           TraversalType := ttPostOrder;
  1038.           Iterate(BSTreeJoinData, false, Self);
  1039.           FIsDataOwner := false;
  1040.           Free;
  1041.         end;
  1042.   end;
  1043. {--------}
  1044. function TBinSearchTree.Replace(Cursor : TTreeCursor; aData : pointer) : pointer;
  1045.   begin
  1046.     Replace := Examine(Cursor);
  1047.     Delete(Cursor);
  1048.     Insert(Cursor, aData);
  1049.   end;
  1050. {--------}
  1051. function  TBinSearchTree.Search(var Cursor : TTreeCursor; aData : pointer) : boolean;
  1052.   var
  1053.     CompResult : integer;
  1054.     Walker     : TTreeCursor;
  1055.   begin
  1056.     Walker := Root;
  1057.     if IsLeaf(Walker) then
  1058.       Search := false
  1059.     else
  1060.       begin
  1061.         CompResult := Compare(aData, Examine(Walker));
  1062.         if      (CompResult < 0) then Walker := Left(Walker)
  1063.         else if (CompResult > 0) then Walker := Right(Walker);
  1064.         while (not IsLeaf(Walker)) and (CompResult <> 0) do
  1065.           begin
  1066.             CompResult := Compare(aData, Examine(Walker));
  1067.             if      (CompResult < 0) then Walker := Left(Walker)
  1068.             else if (CompResult > 0) then Walker := Right(Walker);
  1069.           end;
  1070.         Search := (CompResult = 0);
  1071.       end;
  1072.     Cursor := Walker;
  1073.   end;
  1074. {--------}
  1075. procedure TBinSearchTree.bsSwapData(OldCursor, NewCursor : TTreeCursor);
  1076.   var
  1077.     Data : pointer;
  1078.   begin
  1079.     Data := GetNode(OldCursor)^.Data;
  1080.     GetNode(OldCursor)^.Data := GetNode(NewCursor)^.Data;
  1081.     GetNode(NewCursor)^.Data := Data;
  1082.   end;
  1083. {---------------------------------------------------------------------}
  1084.  
  1085. {$IFNDEF Win32}
  1086. type
  1087.   LH = record L, H : word; end;
  1088. {$ENDIF}
  1089.  
  1090. {=Red-black tree helper routines=====================================
  1091. These routines help out the red-black tree methods. ColorBlack colors
  1092. the cursor black, ColorRed colors the cursor red. IsBlack returns
  1093. true if the cursor is black, whereas IsRed returns true if is red.
  1094. 18Jun95 JMB
  1095. ======================================================================}
  1096. procedure ColorBlack(Cursor : TTreeCursor);
  1097.   {$IFDEF Win32}
  1098.   begin
  1099.     with GetNode(Cursor)^ do
  1100.       PKC := PKC and $FFFFFFFD;
  1101.   end;
  1102.   {$ELSE}
  1103.   near;
  1104.   begin
  1105.     with GetNode(Cursor)^ do
  1106.       LH(PKC).L := LH(PKC).L and $FFFD;
  1107.   end;
  1108.   {$ENDIF}
  1109. {--------}
  1110. function IsBlack(Cursor : TTreeCursor) : boolean;
  1111.   {$IFDEF Win32}
  1112.   var
  1113.     Temp : PNode;
  1114.   begin
  1115.     Temp := GetNode(Cursor);
  1116.     if Assigned(Temp) then
  1117.       IsBlack := (Temp^.PKC and 2) = 0
  1118.     else
  1119.       IsBlack := true;
  1120.   end;
  1121.   {$ELSE}
  1122.   near;
  1123.   var
  1124.     Temp : PNode;
  1125.   begin
  1126.     Temp := GetNode(Cursor);
  1127.     if Assigned(Temp) then
  1128.       IsBlack := (LH(Temp^.PKC).L and 2) = 0
  1129.     else
  1130.       IsBlack := true;
  1131.   end;
  1132.   {$ENDIF}
  1133. {--------}
  1134. procedure ColorRed(Cursor : TTreeCursor);
  1135.   {$IFDEF Win32}
  1136.   begin
  1137.     with GetNode(Cursor)^ do
  1138.       PKC := PKC or 2;
  1139.   end;
  1140.   {$ELSE}
  1141.   near;
  1142.   begin
  1143.     with GetNode(Cursor)^ do
  1144.       LH(PKC).L := LH(PKC).L or 2;
  1145.   end;
  1146.   {$ENDIF}
  1147. {--------}
  1148. function IsRed(Cursor : TTreeCursor) : boolean;
  1149.   {$IFDEF Win32}
  1150.   var
  1151.     Temp : PNode;
  1152.   begin
  1153.     Temp := GetNode(Cursor);
  1154.     if Assigned(Temp) then
  1155.       IsRed := (Temp^.PKC and 2) <> 0
  1156.     else
  1157.       IsRed := false;
  1158.   end;
  1159.   {$ELSE}
  1160.   near;
  1161.   var
  1162.     Temp : PNode;
  1163.   begin
  1164.     Temp := GetNode(Cursor);
  1165.     if Assigned(Temp) then
  1166.       IsRed := (LH(Temp^.PKC).L and 2) <> 0
  1167.     else
  1168.       IsRed := false;
  1169.   end;
  1170.   {$ENDIF}
  1171.  
  1172. {=TrbSearchTree======================================================
  1173. A red-black binary search tree
  1174.  
  1175. A red-black tree is a binary search tree with inbuilt balancing
  1176. algorithms during Insert and Delete. This ensures that the tree does
  1177. not degenerate into a sorted linked list, maintaining its excellent
  1178. search times.
  1179.  
  1180. The tree is called red-black because certain data objects are labelled
  1181. Black and the others are Red such that (1) every Red data object (that
  1182. is not at the root) has a Black parent, (2) each path from leaf to
  1183. root has the same number of Black data objects, and (3) each leaf is
  1184. Black. This set of rules ensures that the tree is (quite) balanced.
  1185.  
  1186. References
  1187.   Sedgewick: Algorithms
  1188.   Wood: Data Structures, Algorithms, and Performance
  1189.  
  1190. PS. I also apologise for the unpolitically correct terminology in this
  1191. source code! Thank you, Bryan, for pointing it out, but it's too late
  1192. now...
  1193. ======================================================================}
  1194. function  TrbSearchTree.Delete(Cursor : TTreeCursor) : TTreeCursor;
  1195.   var
  1196.     Pa, Brother, Nephew1, Nephew2 : TTreeCursor;
  1197.     Balanced : boolean;
  1198.   begin
  1199.     DeletedNodeWasBlack := IsBlack(Cursor);
  1200.     Cursor := inherited Delete(Cursor);
  1201.     Delete := Cursor;
  1202.     repeat
  1203.       Balanced := true;
  1204.       if DeletedNodeWasBlack then
  1205.         if IsRed(Cursor) then
  1206.           ColorBlack(Cursor)
  1207.         else if not IsRoot(Cursor) then
  1208.           begin
  1209.             Pa := Parent(Cursor);
  1210.             if (Kid(Cursor) = CLeft) then
  1211.                  Brother := Right(Pa)
  1212.             else Brother := Left(Pa);
  1213.             if IsRed(Brother) then
  1214.               begin
  1215.                 if IsBlack(Pa) then
  1216.                   ColorBlack(Brother);
  1217.                 ColorRed(Pa);
  1218.                 Brother := rbPromote(Brother);
  1219.                 if (Kid(Cursor) = CLeft) then
  1220.                      Cursor := Left(Left(Brother))
  1221.                 else Cursor := Right(Right(Brother));
  1222.                 Balanced := false;
  1223.               end
  1224.             else {Brother is black}
  1225.               begin
  1226.                 if (Kid(Cursor) = CLeft) then
  1227.                      Nephew1 := Right(Brother)
  1228.                 else Nephew1 := Left(Brother);
  1229.                 if IsRed(Nephew1) then
  1230.                   begin
  1231.                     ColorBlack(Nephew1);
  1232.                     if IsRed(Pa) then
  1233.                       ColorRed(Brother);
  1234.                     ColorBlack(Pa);
  1235.                     Brother := rbPromote(Brother);
  1236.                   end
  1237.                 else {Nephew1 is black}
  1238.                   begin
  1239.                     if (Kid(Cursor) = CLeft) then
  1240.                          Nephew2 := Left(Brother)
  1241.                     else Nephew2 := Right(Brother);
  1242.                     if IsRed(Nephew2) then
  1243.                       begin
  1244.                         if IsBlack(Pa) then
  1245.                           ColorBlack(Nephew2);
  1246.                         ColorBlack(Pa);
  1247.                         Nephew2 := rbPromote(rbPromote(Nephew2));
  1248.                       end
  1249.                     else {Nephew2 is black}
  1250.                       if IsRed(Pa) then
  1251.                         begin
  1252.                           ColorBlack(Pa);
  1253.                           ColorRed(Brother);
  1254.                         end
  1255.                       else {Pa is black}
  1256.                         begin
  1257.                           ColorRed(Brother);
  1258.                           Cursor := Pa;
  1259.                           Balanced := false;
  1260.                         end;
  1261.                   end;
  1262.               end;
  1263.           end;
  1264.     until Balanced;
  1265.   end;
  1266. {--------}
  1267. procedure TrbSearchTree.Insert(var Cursor : TTreeCursor; aData : pointer);
  1268.   var
  1269.     Pa, GrandPa, Uncle : TTreeCursor;
  1270.     Balanced : boolean;
  1271.   begin
  1272.     inherited Insert(Cursor, aData);
  1273.     ColorRed(Cursor);
  1274.     repeat
  1275.       Balanced := true;
  1276.       if not IsRoot(Cursor) then
  1277.         begin
  1278.           Pa := Parent(Cursor);
  1279.           if IsRed(Pa) then
  1280.             if IsRoot(Pa) then
  1281.               ColorBlack(Pa)
  1282.             else
  1283.               begin
  1284.                 GrandPa := Parent(Pa);
  1285.                 ColorRed(GrandPa);
  1286.                 if (Kid(Pa) = CLeft) then
  1287.                      Uncle := Right(GrandPa)
  1288.                 else Uncle := Left(GrandPa);
  1289.                 if IsRed(Uncle) then
  1290.                   begin
  1291.                     ColorBlack(Pa);
  1292.                     ColorBlack(Uncle);
  1293.                     Cursor := GrandPa;
  1294.                     Balanced := false;
  1295.                   end
  1296.                 else {Uncle is black}
  1297.                   if (Kid(Cursor) = Kid(Pa)) then
  1298.                     begin
  1299.                       ColorBlack(Pa);
  1300.                       Pa := rbPromote(Pa);
  1301.                     end
  1302.                   else
  1303.                     begin
  1304.                       ColorBlack(Cursor);
  1305.                       Cursor := rbPromote(rbPromote(Cursor));
  1306.                     end;
  1307.               end;
  1308.         end;
  1309.     until Balanced;
  1310.   end;
  1311. {--------}
  1312. function TrbSearchTree.rbPromote(Cursor : TTreeCursor) : TTreeCursor;
  1313.   var
  1314.     NodeX,
  1315.     NodeP,
  1316.     XSon  : PNode;
  1317.   begin
  1318.     NodeX := GetNode(Cursor);
  1319.     NodeP := Dad(Cursor);
  1320.  
  1321.     with NodeP^ do
  1322.       begin
  1323.         Dad(PKC)^.TLink[Kid(PKC)] := NodeX;
  1324.         NodeX^.PKC := Dye(PKC, NodeX^.PKC);
  1325.       end;
  1326.  
  1327.     if (Kid(Cursor) = CLeft) then
  1328.       begin
  1329.         XSon := NodeX^.TLink[CRight];
  1330.         NodeX^.TLink[CRight] := NodeP;
  1331.         NodeP^.PKC := Dye(Csr(NodeX, CRight), NodeP^.PKC);
  1332.         NodeP^.TLink[CLeft] := XSon;
  1333.         if (XSon <> nil) then
  1334.           XSon^.PKC := Dye(Cursor, XSon^.PKC);
  1335.       end
  1336.     else
  1337.       begin
  1338.         XSon := NodeX^.TLink[CLeft];
  1339.         NodeX^.TLink[CLeft] := NodeP;
  1340.         NodeP^.PKC := Dye(Csr(NodeX, CLeft), NodeP^.PKC);
  1341.         NodeP^.TLink[CRight] := XSon;
  1342.         if (XSon <> nil) then
  1343.           XSon^.PKC := Dye(Cursor, XSon^.PKC);
  1344.       end;
  1345.  
  1346.     rbPromote := Bleach(NodeX^.PKC);
  1347.   end;
  1348. {--------}
  1349. procedure TrbSearchTree.bsSwapData(OldCursor, NewCursor : TTreeCursor);
  1350.   begin
  1351.     DeletedNodeWasBlack :=  IsBlack(NewCursor);
  1352.     inherited bsSwapData(OldCursor, NewCursor);
  1353.   end;
  1354. {---------------------------------------------------------------------}
  1355.  
  1356. end.
  1357.